package utils;

import com.alibaba.fastjson.JSON;
import com.itextpdf.barcodes.Barcode128;
import com.itextpdf.barcodes.BarcodeQRCode;
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.colors.Color;
import com.itextpdf.kernel.colors.DeviceRgb;
import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.annot.PdfCircleAnnotation;
import com.itextpdf.kernel.pdf.annot.PdfSquareAnnotation;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.borders.Border;
import com.itextpdf.layout.borders.SolidBorder;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Image;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.property.HorizontalAlignment;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.UnitValue;
import com.itextpdf.layout.property.VerticalAlignment;
import entry.Column;
import entry.Panel;
import entry.Panels;
import entry.PrintElements;
import entry.options.*;
import enums.*;
import lombok.Data;
import org.apache.commons.collections4.ListUtils;

import java.awt.geom.Rectangle2D;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.*;

/**
 * @Author LS
 * @Date 2023/4/23 11:41
 * @Description
 **/

public class HiPrintItextUtils {

    // PDF文档
    private PdfDocument pdfDocument;

    private Document document;

    // PDF结构
    private Panels panels;

    // 用于保存数据所需内部类
    private UtilData utilData;

    // 未完成数据填充的页面
    private List<PdfPage> notIssuePageCache = new ArrayList<>();

    // page对应的所需绘制表格
    private Map<PdfPage, Map<TableOptions, float[]>> pageTableCache = new HashMap<>();

    // 需要进行打印的数据
    private Map<PdfPage, List<PrintElements>> printElementsPageCache = new HashMap<>();

    // pdf写出工具
    private PdfWriter pdfWriter;

    // 毫米与像素转换单位
    private final double mmToPx = 2.83;

    // pt与像素px的转换
    private final double ptToPx = 1.33;


    public HiPrintItextUtils(String json, String filePath) throws FileNotFoundException {
        this.panels = getPanels(json);
        // 创建指定大小的页面
        pdfWriter = new PdfWriter(new FileOutputStream(filePath));
        pdfDocument = new PdfDocument(pdfWriter);
        document = new Document(pdfDocument);
    }

    @Data
    public static class UtilData {
        // 文本框绑定的字段 Map<'fieldKey', 'filedValue'>
        private Map<String, String> fields = new HashMap<>();

        // 每个表格对应的数据 Map<'tableKey', List<Map<'headerKey','fieldValue'>>> 若无headerKey兼容headerName
        private Map<String, List<Map<String, String>>> tableData = new HashMap<>();
    }

    public void setUtilData(UtilData utilData){
        this.utilData = utilData;
    }

    private Panels getPanels(String json){
        return JSON.parseObject(json, Panels.class);
    }

    /**
     * 创建新的页面
     */
    private PdfPage createPage(Panel panel){
        return createPage(panel, true);
    }

    private PdfPage createPage(Panel panel, boolean addCache){
        PdfPage newPage = pdfDocument.addNewPage(new PageSize((float) (panel.getWidth() * mmToPx), (float) (panel.getHeight() * mmToPx)));
        if (!addCache){
            notIssuePageCache.add(newPage);
        }
        return newPage;
    }



    /**
     * 保存
     * @throws IOException
     */
    public void save() throws IOException {
        try {
            // 构建返回流
            for (Panel panel : panels.getPanels()) {
                PdfPage page = createPage(panel);
                // 创建页面
                List<PrintElements> printElements = panel.getPrintElements();
                for (PrintElements printElement : printElements) {
                    dealOptions(page, printElement);
                }
                pdfDocument.addEventHandler(PdfDocumentEvent.END_PAGE, new HeaderFooterHandler(panel));
            }
            // 遍历对应的page与textOption
            for (Map.Entry<PdfPage, Map<TableOptions, float[]>> next : pageTableCache.entrySet()) {
                PdfPage pageBase = next.getKey();
                Map<TableOptions, float[]> value = next.getValue();
                for (Map.Entry<TableOptions, float[]> tableOptionsMap : value.entrySet()) {
                    TableOptions tableOptions = tableOptionsMap.getKey();
                    // 创建表格
                    createTable(pageBase, tableOptions);
                }
            }
            Collection<List<PrintElements>> values = printElementsPageCache.values();
            if (!values.isEmpty()) {
                List<PrintElements> printElementsList = new ArrayList<>();
                values.forEach(printElementsList::addAll);
                // 循环未进行其他打印元素缓存
                for (PdfPage pageBase : notIssuePageCache) {
                    for (PrintElements printElements : printElementsList) {
                        dealOptions(pageBase, printElements);
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            document.close();
            pdfWriter.close();
        }
    }

    /**
     * 处理Options结构，根据不同的Options生成不同的PDF元素
     * @param printElement
     */
    private void dealOptions(PdfPage page ,PrintElements printElement) throws Exception {
        Options options = printElement.getOptions();
        Rectangle pageRectangle = page.getPageSize();
        // 页面高度
        float pageHeight = (float) (pageRectangle.getHeight() /* * ptToPx*/);
        // 元素距离页面左边的距离 px
        float optionsLeft = (float) (options.getLeft() /* * ptToPx*/);
        // 元素距离顶部的距离 px
        float optionsTop = (float) (options.getTop() /* * ptToPx*/);
        // 元素高度 px
        float optionsHeight = (float) (options.getHeight() /* * ptToPx*/);
        // 元素宽度 px
        float optionsWidth = (float) (options.getWidth() /* * ptToPx*/);
        // 元素距离底部的距离 px：页面高度 - 元素距离顶部的距离 - 元素高度
        float optionsBottom = pageHeight - optionsTop - optionsHeight;
        if (options instanceof TextOptions){
            TextOptions textOptions = (TextOptions) options;
            OptionsTextTypeEnums textType = textOptions.getTextType();
            // 若传入字段不为空，需要通过数据字段获取值
            if (OptionsTextTypeEnums.TEXT.equals(textType)){
//                // 无字段名时，绘制text
//                if (textOptions.getField() != null){
//                    createTextBoxField(page, textOptions, optionsLeft, optionsBottom, optionsWidth);
//                }else {
//                    // 绘制字符串
//                createString(page, textOptions, optionsLeft, optionsBottom, optionsWidth);

//                }
                createString(page, textOptions, optionsLeft, optionsBottom, optionsWidth);
            }else if (OptionsTextTypeEnums.BARCODE.equals(textType)){
                Rectangle rectangle = new Rectangle(optionsLeft, optionsBottom, optionsWidth, optionsHeight);
                createBarcode(page, textOptions, optionsLeft, optionsBottom, optionsWidth, rectangle);
            }else if (OptionsTextTypeEnums.QRCODE.equals(textType)){
                createQrcode(page, textOptions, optionsLeft, optionsBottom, optionsWidth);
            }else {
                // 不是有效枚举，跳过插入元素 todo doLog
            }
        }else if (options instanceof LongTextOptions){
            LongTextOptions longTextOptions = (LongTextOptions) options;
            createLongText(page, longTextOptions, optionsLeft, optionsBottom, optionsWidth);
        }else if (options instanceof TableOptions){
            // todo 根据绘制方式区分绘制方式，
            //  1、表格数据大于表格大小时，复制当前页面所有数据，另起一页
            //  2、表格数据往后推并且是否重复表头
            TableOptions tableOptions = (TableOptions) options;
            // 后置绘制，根据不同的方式绘制页面
            addPageTableCache(page, tableOptions, new float[]{optionsLeft, optionsBottom, optionsWidth});
//            createTable(page, tableOptions, optionsLeft, optionsBottom, optionsWidth);
        }else if (options instanceof ImageOptions){
            ImageOptions imageOptions = (ImageOptions) options;
            createImage(page, imageOptions, optionsLeft, optionsBottom, optionsWidth);
        }else if (options instanceof  GraphicalOptions){
            Rectangle rectangle = new Rectangle(optionsLeft, optionsBottom, optionsWidth, optionsHeight);
            createGraph(page, printElement, rectangle);
        }else {
            throw new RuntimeException("无效元素");
        }
        // 不为表格类型的打印数据进行缓存
        if (! (options instanceof TableOptions)){
            // 加入打印缓存
            addPrintElementsPageCache(page, printElement);
        }
    }

    /**
     * 加入缓存，后续进行绘制，绘制内容范围为table范围
     * @param pageBase
     * @param tableOptions
     * @param position
     */
    private void addPageTableCache(PdfPage pageBase, TableOptions tableOptions, float[] position){
        // 检查缓存
        if (pageTableCache == null) {
            pageTableCache = new HashMap<>();
        }
        // 若不存在pageKey，直接存入
        if (!pageTableCache.containsKey(pageBase)){
            Map<TableOptions, float[]> map = new HashMap<>();
            map.put(tableOptions, position);
            pageTableCache.putIfAbsent(pageBase, map);
        }
        else {
            Map<TableOptions, float[]> map = pageTableCache.get(pageBase);
            map.putIfAbsent(tableOptions, position);
            pageTableCache.put(pageBase, map);
        }
    }


    /**
     * 增加页面对应的打印数据缓存
     * @param pageBase
     * @param printElements
     */
    private void addPrintElementsPageCache(PdfPage pageBase, PrintElements printElements){
        if (printElementsPageCache == null) {
            printElementsPageCache = new HashMap<>();
        }
        if (printElementsPageCache.containsKey(pageBase)) {
            List<PrintElements> printElementsList = printElementsPageCache.get(pageBase);
            printElementsList.add(printElements);
            printElementsPageCache.put(pageBase, printElementsList);
        }
        else {
            ArrayList<PrintElements> printElementsList = new ArrayList<>();
            printElementsList.add(printElements);
            printElementsPageCache.put(pageBase, printElementsList);
        }
    }

    /**
     * 创建矩形，原型，等图形
     * @param page
     * @param printElement
     * @param rectangle
     */
    private void createGraph(PdfPage page, PrintElements printElement, Rectangle rectangle) {
        PrintElementTypeEnums type = printElement.getPrintElementType().getType();
        // 详细设置样式
        GraphicalOptions options = (GraphicalOptions) printElement.getOptions();
        float x = rectangle.getX();
        float y = rectangle.getY();
        float height = rectangle.getHeight();
        float width = rectangle.getWidth();
        if (PrintElementTypeEnums.HLINE.equals(type)){
            // 横线
            PdfCanvas pdfCanvas = new PdfCanvas(page);
            pdfCanvas.setStrokeColor(hex2RGB(options.getBorderColor()));
            pdfCanvas.moveTo(x, y + height).lineTo(x + width, y + height).stroke();
        }else if (PrintElementTypeEnums.VLINE.equals(type)){
            // 竖线
            PdfCanvas pdfCanvas = new PdfCanvas(page);
            pdfCanvas.setStrokeColor(hex2RGB(options.getBorderColor()));
            pdfCanvas.moveTo(x, y).lineTo(x, y + height).stroke();
        }else if (PrintElementTypeEnums.HTML.equals(type)){
            // todo
        }else if (PrintElementTypeEnums.RECT.equals(type)){
            // 矩形
            PdfSquareAnnotation annotation = new PdfSquareAnnotation(rectangle);
            annotation.setColor(hex2RGB(options.getBorderColor()));
            page.addAnnotation(annotation);
        }else if (PrintElementTypeEnums.OVAL.equals(type)){
            // 椭圆
            PdfCircleAnnotation annotation = new PdfCircleAnnotation(rectangle);
            annotation.setColor(hex2RGB(options.getBorderColor()));
            page.addAnnotation(annotation);
        }
    }

    /**
     * 创建图片
     * @param page
     * @param imageOptions
     * @param left
     * @param bottom
     * @param width
     * @throws MalformedURLException
     */
    private void createImage(PdfPage page, ImageOptions imageOptions, float left, float bottom, float width) throws MalformedURLException {
        String value = imageOptions.getSrc();
        if (imageOptions.getField() != null && utilData != null && utilData.getFields() != null) {
            if (utilData.getFields().containsKey(imageOptions.getField())) {
                value = utilData.getFields().get(imageOptions.getField());
            }
        }
        ImageData imageData = ImageDataFactory.create(value);
        Image image = new Image(imageData);
        image.setFixedPosition(pdfDocument.getPageNumber(page), left, bottom, width);
        document.add(image);
    }

    /**
     * 创建表格
     * @param tableOptions
     */
    private void createTable(PdfPage page, TableOptions tableOptions) throws IOException {
        List<Column> columns = tableOptions.getColumns().get(0);
        // 获取每个表格的宽度
        float[] columnWidthArray = new float[columns.size()];
        for (int i = 0; i < columns.size(); i++) {
            columnWidthArray[i] = columns.get(i).getWidth().floatValue();
        }
        // 创建表格，设定每列的宽度
        Table table = new Table(columnWidthArray);
        table.setMargin(0f);
        table.setPadding(0f);
        // 表格边框
        Border[] tableBorder = getBorder(tableOptions.getTableBorder());
        table.setBorderTop(tableBorder[0]);
        table.setBorderRight(tableBorder[1]);
        table.setBorderBottom(tableBorder[2]);
        table.setBorderLeft(tableBorder[3]);
        // 设置表头行高
        float headerCellHeight = 21f;
        if (tableOptions.getTableHeaderRowHeight() > 0){
            headerCellHeight = (float) (tableOptions.getTableHeaderRowHeight() /* * ptToPx*/);
        }else {
            tableOptions.setTableHeaderRowHeight(headerCellHeight);
        }
        // 获取表头背景色
        Color tableHeaderBackground = hex2RGB(tableOptions.getTableHeaderBackground(), new java.awt.Color(223, 223, 223));
        // 表头字体
        PdfFont tableHeaderFont = getFont(tableOptions.getFontFamily(), (int) tableOptions.getTableHeaderFontSize(), tableOptions.getTableHeaderFontWeight());
        // 表体字体
        PdfFont tableBodyFont = getFont(tableOptions.getFontFamily(), tableOptions.getFontSize(), null);
        // 循环表头
        for (Column column : columns) {
            String columnTitle = column.getTitle();
            if (columnTitle == null){
                columnTitle = "";
            }
            // 创建表头
            Cell cell = new Cell(column.getRowspan(), column.getColspan());
            // 表头背景色
            cell.setBackgroundColor(tableHeaderBackground);
            // 创建元素并设置字体
            Paragraph paragraph = new Paragraph(columnTitle);
            paragraph.setFont(tableHeaderFont);
            // 字体大小
            paragraph.setFontSize((float) (tableOptions.getTableHeaderFontSize() /* * ptToPx*/));
            // 设置为居中
            paragraph.setVerticalAlignment(VerticalAlignment.MIDDLE);
            paragraph.setHorizontalAlignment(HorizontalAlignment.CENTER);
            paragraph.setTextAlignment(TextAlignment.CENTER);
//            paragraph.setHeight(headerCellHeight);
//            paragraph.setMargin(0f);
//            paragraph.setPadding(0f);
            // 单元格添加元素
            cell.add(paragraph);
            cell.setHeight(headerCellHeight);
            cell.setMargin(0f);
            cell.setPadding(0f);
            table.addCell(cell);
        }
        // 设置表格大小
        float optionsLeft = (float) tableOptions.getLeft();
        float optionsWidth = (float) tableOptions.getWidth();
        float optionsBottom = fillData(page, tableOptions, table);
        // 设置元素位置
        table.setFixedPosition(pdfDocument.getPageNumber(page), optionsLeft, optionsBottom, optionsWidth);
        document.add(table);
    }

    /**
     * 填充数据
     * @param page
     * @param tableOptions
     * @param table
     * @return 返回页面距离底部的高度
     */
    private float fillData(PdfPage page, TableOptions tableOptions, Table table) throws IOException {
        float pageHeight = page.getPageSize().getHeight();
        float optionsHeight = (float) tableOptions.getHeight();
        float optionsTop = (float) tableOptions.getTop();
        // 元素底部大小
        float optionsBottom = pageHeight - optionsHeight - optionsTop;
        // 表格数据量
        int dataSize = 0;
        // 表格绑定字段
        String tableField = tableOptions.getField();
        List<Column> columns = tableOptions.getColumns().get(0);
        // 填充数据
        if (utilData != null && !utilData.getTableData().isEmpty()){
            int tableMaxSize = getTableMaxSize(tableOptions);
            Map<String, List<Map<String, String>>> tableData = utilData.getTableData();
            // 获取传入数据
            List<Map<String, String>> utilDataList = utilData.getTableData().get(tableField);
            // 分割数据大小
            List<List<Map<String, String>>> partition = ListUtils.partition(utilDataList, tableMaxSize);
            List<Map<String, String>> columnData = new ArrayList<>(partition.get(0));
            dataSize = columnData.size();
            // 循环分割后的数据
            for (Map<String, String> columnDatum : columnData) {
                for (Column column : columns) {
                    Cell cell = new Cell();
                    // 通过表头ID获取值
                    String columnValueByField = columnDatum.get(column.getField());
                    // 通过表头名称获取值
                    String columnValueByTitle = columnDatum.get(column.getTitle());
                    String columnValue = null;
                    if (columnValueByField != null) {
                        columnValue = columnValueByField;
                    }
                    if (columnValueByTitle != null) {
                        columnValue = columnValueByTitle;
                    }
                    if (columnValue == null){
                        columnValue = "";
                    }
                    // 设置值
                    Paragraph paragraph = new Paragraph(columnValue);
                    paragraph.setTextAlignment(TextAlignment.CENTER);
                    paragraph.setHorizontalAlignment(HorizontalAlignment.CENTER);
                    paragraph.setVerticalAlignment(VerticalAlignment.MIDDLE);
//                    paragraph.setHeight((float) tableOptions.getTableBodyRowHeight());
//                    paragraph.setMargin(0f);
//                    paragraph.setPadding(0f);
                    cell.add(paragraph);
                    cell.setHeight((float) tableOptions.getTableBodyRowHeight());
                    cell.setMargin(0f);
                    cell.setPadding(0f);
                    table.addCell(cell);
                }
            }
            utilDataList.removeAll(columnData);
            // 移除数据
            tableData.put(tableField, utilDataList);
            // 更新缓存
            utilData.setTableData(tableData);
            // 仍存在数据，新建一页并填充表单
            if (!tableData.get(tableField).isEmpty()) {
                for (Panel panel : panels.getPanels()) {
                    PdfPage newPage = createPage(panel, false);
                    createTable(newPage, tableOptions);
                }
            }
            // 设置元素底部
            optionsBottom = (float) (pageHeight - optionsTop - optionsHeight
                    + (tableMaxSize - dataSize) * ((optionsHeight - tableOptions.getTableHeaderRowHeight()) / tableMaxSize)
            );
        }

        return optionsBottom;
    }

    /**
     * 获取表格大小
     * @param tableOptions
     * @return
     */
    private int getTableMaxSize(TableOptions tableOptions) throws IOException {
        double tableBodyRowHeight = tableOptions.getTableBodyRowHeight();
        double optionsHeight = tableOptions.getHeight();
        if (tableBodyRowHeight <= 0){
            tableBodyRowHeight = 16;
            tableOptions.setTableBodyRowHeight(16);
        }
        return (int) Math.floor((optionsHeight - tableOptions.getTableHeaderRowHeight()) / tableBodyRowHeight);
    }


    /**
     * 创建长文本
     * @param page
     * @param longTextOptions
     * @param left
     * @param bottom
     * @param width
     * @throws IOException
     */
    private void createLongText(PdfPage page, LongTextOptions longTextOptions, float left, float bottom, float width) throws IOException {
        TextOptions textOptions = longTextOptions.convertToTextOptions();
        createString(page, textOptions, left, bottom, width);
    }

    /**
     * 创建二维码
     * @param page
     * @param textOptions
     * @param left
     * @param bottom
     * @param width
     */
    private void createQrcode(PdfPage page, TextOptions textOptions, float left, float bottom, float width) throws IOException {
        String value = textOptions.getTitle();
        // 从传入值中获取
        if (textOptions.getField() != null && !textOptions.getField().isEmpty() && utilData != null){
            if (utilData.getFields() != null && utilData.getFields().containsKey(textOptions.getField())){
                value = utilData.getFields().get(textOptions.getField());
            }
        }
        BarcodeQRCode barcodeQRCode = new BarcodeQRCode(value);
        PdfFormXObject formXObject = barcodeQRCode.createFormXObject(hex2RGB(textOptions.getColor()), pdfDocument);
        Image image = new Image(formXObject);
        image.setWidth((float) (textOptions.getWidth() /* * ptToPx*/));
        image.setHeight((float) (textOptions.getHeight() /* * ptToPx*/));
        image.setFixedPosition(pdfDocument.getPageNumber(page), left, bottom, width);
        document.add(image);
    }

    /**
     * 创建条形码
     * @param page
     * @param textOptions
     * @param left
     * @param bottom
     * @param width
     */
    private void createBarcode(PdfPage page, TextOptions textOptions, float left, float bottom, float width, Rectangle rectangle) {
        String value = textOptions.getTitle();
        // 从传入值中获取
        if (textOptions.getField() != null && !textOptions.getField().isEmpty() && utilData != null){
            if (utilData.getFields() != null && utilData.getFields().containsKey(textOptions.getField())){
                value = utilData.getFields().get(textOptions.getField());
            }
        }
        Barcode128 barcode128 = new Barcode128(pdfDocument);
        barcode128.setCode(value);
//        barcode128.setSize(0);
//        barcode128.setBarHeight((float) (textOptions.getHeight() / mmToPx));
        Color color = hex2RGB(textOptions.getColor());
        // 创建图片
        PdfFormXObject formXObject = barcode128.createFormXObject(color, color, pdfDocument);
        Image image = new Image(formXObject);
        image.setWidth((float) (textOptions.getWidth() /* * ptToPx*/));
        image.setHeight((float) (textOptions.getHeight() /* * ptToPx*/));
        image.setFixedPosition(pdfDocument.getPageNumber(page), left, bottom, width);
        document.add(image);

//        PdfSquareAnnotation annotation = new PdfSquareAnnotation(rectangle);
//        page.addAnnotation(annotation);
    }

    /**
     * 创建指定区域文本
     * @param page
     * @param textOptions
     * @param left
     * @param bottom
     * @param width
     * @throws IOException
     */
    private void createString(PdfPage page, TextOptions textOptions, float left, float bottom, float width) throws IOException {
        // 获取标题
        String title = textOptions.getTitle();
        if (title == null || title.isEmpty()){
            title = "";
        }
        // 获取传入参数中的值
        String field = textOptions.getField();
        String value = null;
        if (utilData != null && utilData.getFields() != null && field != null){
            value = utilData.getFields().get(field);
        }
        StringBuilder elementValue = new StringBuilder(title);
        // 若传入值
        if (value != null && !value.isEmpty()){
            if (title.length() > 0){
                elementValue.append("：");
            }
            elementValue.append(value);
        }

        // 文字字体
        PdfFont font = getFont(textOptions.getFontFamily(), (int) textOptions.getFontSize(), textOptions.getFontWeight());
        // 设置元素及元素位置
        Paragraph paragraph = new Paragraph(elementValue.toString());
        // 设置字体颜色
        paragraph.setFontColor(hex2RGB(textOptions.getColor()));
        // 设置字体
        paragraph.setFont(font);
        // 字体大小
        paragraph.setFontSize((float) (textOptions.getFontSize() /* * ptToPx*/));
        // 字体间距
        paragraph.setCharacterSpacing((float) (textOptions.getLetterSpacing() /* * ptToPx*/));
        // 文字对齐
        paragraph.setTextAlignment(getTextAlign(textOptions.getTextAlign()));
        // 文字在文本域中的对齐
        paragraph.setHorizontalAlignment(getHorizontalAlignment(textOptions.getTextAlign()));
        paragraph.setVerticalAlignment(getVerticalAlignment(textOptions.getTextContentVerticalAlign()));

        // 设置文本框位置
        paragraph.setFixedPosition(pdfDocument.getPageNumber(page), left, bottom, width);
        document.add(paragraph);
    }

    /**
     * 十六进制颜色转换为RGB颜色
     * @param hexStr
     * @param defaultColor
     * @return
     */
    private Color hex2RGB(String hexStr, java.awt.Color defaultColor){
        if(hexStr != null && hexStr.length() == 7){
            int R = Integer.valueOf(hexStr.substring( 1, 3 ), 16);
            int G = Integer.valueOf(hexStr.substring( 3, 5 ), 16);
            int B = Integer.valueOf(hexStr.substring( 5, 7 ), 16);
            return new DeviceRgb(R, G, B);
        }
        return new DeviceRgb(defaultColor.getRed(), defaultColor.getGreen(), defaultColor.getBlue());
    }

    private Color hex2RGB(String hexStr){
        return this.hex2RGB(hexStr, java.awt.Color.BLACK);
    }

    /**
     * 获取边框
     * @param borderEnums
     * @return Border[top,right,left,bottom]
     */
    private Border[] getBorder(BorderEnums borderEnums){
        SolidBorder solidBorder = new SolidBorder(1f);
        Border[] borders = new Border[]{null, null, null, null};
        if (borderEnums != null){
            if (BorderEnums.BORDER.equals(borderEnums)) {
                borders = new Border[]{solidBorder, solidBorder, solidBorder, solidBorder};
            }else if (BorderEnums.BOTTOM_BORDER.equals(borderEnums)){
                borders = new Border[]{null, null, solidBorder, null};
            }else if (BorderEnums.TOP_BORDER.equals(borderEnums)){
                borders = new Border[]{solidBorder, null, null, null};
            }else if (BorderEnums.TOP_BOTTOM_BORDER.equals(borderEnums)){
                borders = new Border[]{solidBorder, null, solidBorder, null};
            }
        }
        return borders;
    }

    /**
     * todo 获取字体
     * @param fontFamily
     * @param fontSize
     * @param fontWidth
     * @return
     */
    protected static PdfFont getFont(String fontFamily, int fontSize, String fontWidth) throws IOException {
        // todo itext默认字体不支持中文，需要使用ttf文件指定
        if (fontFamily == null || fontFamily.isEmpty()){
            fontFamily = "";
        }
        if (fontSize <= 0){
            fontSize = 12;
        }
        if (fontWidth == null || fontWidth.isEmpty()){
            fontWidth = "";
        }
        return PdfFontFactory.createFont("/fonts/文鼎PL简报宋.ttf", PdfEncodings.IDENTITY_H, true);
    }

    private PdfFont getFont() throws IOException {
        return getFont(null, 0, null);
    }

    /**
     * 获取文字对齐
     * @param textAlignEnums
     * @return
     */
    private TextAlignment getTextAlign(TextAlignEnums textAlignEnums){
        if (textAlignEnums != null){
            if (TextAlignEnums.CENTER.equals(textAlignEnums)){
                return TextAlignment.CENTER;
            }else if (TextAlignEnums.JSUTIFY.equals(textAlignEnums)){
                return TextAlignment.JUSTIFIED;
            }else if (TextAlignEnums.LEFT.equals(textAlignEnums)){
                return TextAlignment.LEFT;
            }else if (TextAlignEnums.RIGHT.equals(textAlignEnums)){
                return TextAlignment.RIGHT;
            }
        }
        return TextAlignment.CENTER;
    }

    /**
     * 获取左右对齐
     * @param textAlignEnums
     * @return
     */
    private HorizontalAlignment getHorizontalAlignment(TextAlignEnums textAlignEnums){
        if (textAlignEnums != null){
            if (TextAlignEnums.CENTER.equals(textAlignEnums)){
                return HorizontalAlignment.CENTER;
            }else if (TextAlignEnums.LEFT.equals(textAlignEnums)){
                return HorizontalAlignment.LEFT;
            }else if (TextAlignEnums.RIGHT.equals(textAlignEnums)){
                return HorizontalAlignment.RIGHT;
            }
        }
        return HorizontalAlignment.LEFT;
    }

    /**
     * 获取上下对齐
     * @param verticalAlignEnums
     * @return
     */
    private VerticalAlignment getVerticalAlignment(TextVerticalAlignEnums verticalAlignEnums){
        if (verticalAlignEnums != null){
            if (TextVerticalAlignEnums.BOTTOM.equals(verticalAlignEnums)){
                return VerticalAlignment.BOTTOM;
            }else if (TextVerticalAlignEnums.TOP.equals(verticalAlignEnums)){
                return VerticalAlignment.TOP;
            }else if (TextVerticalAlignEnums.MIDDLE.equals(verticalAlignEnums)){
                return VerticalAlignment.MIDDLE;
            }
        }
        return VerticalAlignment.TOP;
    }
}
